local AB = OneRingLib and OneRingLib.ext and OneRingLib.ext.ActionBook
assert(AB and AB:compatible(1,0), "Requires a compatible version of ActionBook")

local function generateColor(c, n)
	local hue, v, s = (15+(c-1)*360/n)%360, 1, 0.85;

	local h = floor(hue/60) % 6;
	local f = (hue/60) % 1;
	local p, q, t = v - v * s, v - v * f * s, v - v*s + v * f * s;
	if h == 0 then return v, t, p;
	elseif h == 1 then return q, v, p;
	elseif h == 2 then return p, v, t;
	elseif h == 3 then return p, q, v;
	elseif h == 4 then return t, p, v;
	elseif h == 5 then return v, p, q;
	end
end

do -- OPieTrinkets
	OneRingLib:CreateRing("OPieTrinkets", {
		{AB:get("item", (GetInventorySlotInfo("Trinket0Slot")), false, true), r=0.05, g=0.75, b=0.95}, -- top
		{AB:get("item", (GetInventorySlotInfo("Trinket1Slot")), false, true), r=0.95, g=0.75, b=0.05}, -- bottom
		name="Trinkets"
	});
end
do -- OPieTracker
	local rname, rdesc, map, ringID = "OPieTracker", {
		name="Tracking", hotkey="ALT-F"
	}, {};
	local function setTracking(id)
		SetTracking(id, not select(3, GetTrackingInfo(id)));
	end
	local function hint(aid)
		local name, tex, on, typ = GetTrackingInfo(map[aid]);
		return name, on and 1 or 0, tex, name, 0,0,0
	end
	local trackerActions = setmetatable({}, {__index=function(t, k)
		t[k] = AB:create("func", hint, setTracking, k)
		map[t[k]] = k
		return t[k]
	end})
	function rdesc.preClick()
		local n = GetNumTrackingTypes();
		if n ~= #rdesc then
			for i=1,n do
				rdesc[i] = rdesc[i] or {}; local t = rdesc[i];
				t[1], t.r, t.g, t.b = trackerActions[i], generateColor(i,n);
			end
			for i=n+1,#rdesc do
				rdesc[i] = nil;
			end
			OneRingLib:SetRingData(ringID, rdesc);
		end
	end
	ringID = OneRingLib:CreateRing(rname, rdesc);
	EC_Register("PLAYER_ENTERING_WORLD", "OPie.AutoTracker", function() return "remove", rdesc.preClick(ringID); end);
end
do -- OPieAutoQuest
	local whitelist = {[37888]=true, [37860]=true, [37859]=true, [37815]=true, [46847]=true, [47030]=true, [39213]=true, [42986]=true, [49278]=true};
	local rname, rdesc, rid = "OPieAutoQuest", {
		name="Quest Items", hotkey="ALT-Q"
	};
	rid = OneRingLib:CreateRing(rname, rdesc);

	local inring, fastClickItem = {};
	local function scanInventory()
		local changed = false;

		-- Save which item is the /current/ fast click item so syncRing can later restore that status
		fastClickItem = select(7, OneRingLib:GetRingInfo(rid));
		fastClickItem = rdesc and rdesc[fastClickItem] and rdesc[fastClickItem].xiid;

		-- Search quests for activation items
		local questItemIDs = {};
		for i=1,GetNumQuestLogEntries() do
			local link, icon, charges, showWhenComplete = GetQuestLogSpecialItemInfo(i);
			if link and (showWhenComplete or not select(7, GetQuestLogTitle(i))) then questItemIDs[tonumber(link:match("item:(%d+)"))] = true; end
		end

		-- Shuffle through the bags
		for bag=0,4 do
			for slot=1,GetContainerNumSlots(bag) do
				local iid = GetContainerItemID(bag, slot);
				local isQuest, startQuestId, isQuestActive = GetContainerItemQuestInfo(bag, slot);
				isQuest = iid and ((isQuest and GetItemSpell(iid)) or whitelist[iid] or questItemIDs[iid] or (startQuestId and not isQuestActive));
				if isQuest then
					if not inring[iid] then
						rdesc[#rdesc+1], inring[iid], changed = {AB:get("item", iid), used=true, xiid=iid}, #rdesc+1, true;
					else
						rdesc[inring[iid]].used = true;
					end
				end
			end
		end

		-- Check whether any of our quest items are equipped... Hi, Egan's Blaster.
		for i=0,19 do
			local j = inring[GetInventoryItemID("player", i)];
			if j and rdesc[j] then rdesc[j].used = true; end
		end

		-- Drop any items in the ring we haven't found.
		local t = 1;
		for k=1,#rdesc do local v = rdesc[k];
			if v.used then
				rdesc[t], inring[v.xiid], v.used, t = rdesc[k], t, nil, t + 1;
			else
				inring[v.xiid] = nil;
			end
		end
		for k=t,#rdesc do rdesc[k], changed = nil, true; end

		return changed;
	end
	local function syncRing()
		local n = #rdesc;
		for i, d in ipairs(rdesc) do
			d.fastClick, d.r, d.g, d.b = true, generateColor(i, n);
			if fastClickItem and d.xiid == fastClickItem then rdesc.fastClickSlice = i; end
		end
		OneRingLib:SetRingData(rid, rdesc);
	end
	local function pvarNotify(event, name, var)
		if event == "LOADED" then
			fastClickItem, var.fastClick = var.fastClick, fastClickItem;
			syncRing();
		elseif event == "LOGOUT" and rid then
			local fcslice = select(7, OneRingLib:GetRingInfo(rid)) or nil;
			var.fastClick = fcslice and rdesc[fcslice] and rdesc[fcslice].xiid or nil;
		end
	end
	function rdesc.preClick(ring, id, force)
		if scanInventory() then
			syncRing();
		end
	end
	EC_Register("PLAYER_REGEN_DISABLED", "OPie.AutoQuest", rdesc.preClick);
end